<?php
namespace Modules\Order\Entities;

use Modules\Core\Entities\BaseEntity as Model;
use Modules\Order\Entities\OrderSku;
use Modules\Order\Entities\OrderAddress;
use Modules\Order\Entities\Sku;

use Modules\Coupon\Entities\UserCoupon;
use ThrowException;

use Modules\Core\Traits\DeviceMarkable;

use DB;
use Auth;
use Setting;
use Payment;

// 基础订单类，可扩展出MovieOrder  MusicOrder   ArticleOrder 等订单类
class BaseOrder extends Model
{
    use DeviceMarkable;
    
    protected $guarded = [];
    protected $table = 'orders';

    static public $resourceName = '订单';
    static public $orderType = NULL;

    public $skusTemp = [];
    public $addressTemp = NULL;
    public $isAutoComplete = false;
    public $tempUser = NULL;
    public $tempExchangeRecord = NULL;
    public $userCouponTemp = NULL;

    public $isUseRedpack = 0;     // 是否使用红包

    static public $isVisible = true;     // 未付款时是否可见
    static public $autoClosedTimeout = 30;    // 自动关闭时间，默认为30分钟

    // 数据库中字段
    public $is_need_address = 0;

    protected $casts = [
        'options' => 'array',
    ];

    protected $appends = ['union_status', 'node_type_text', 'union_status_text', 'activity_type_text', 'is_closeable'];

    // 下单的sku
    public function skus()
    {
        return $this->hasMany('\Modules\Order\Entities\OrderSku', 'order_id');
    }

    public function offline_skus()
    {
        return $this->skus()->whereNull('sku_type')->orWhere('sku_type', 'custom');
    }

    // 下单地址
    public function address()
    {
        return $this->hasOne('\Modules\Order\Entities\OrderAddress', 'order_id');
    }

    public function sku()
    {
        return $this->hasOne('\Modules\Order\Entities\OrderSku', 'order_id');
    }

    // 售后
    public function aftersale()
    {
        return $this->hasOne('\Modules\Order\Entities\Aftersale', 'order_id');
    }

    // 售后
    public function aftersales()
    {
        return $this->hasMany('\Modules\Order\Entities\Aftersale', 'order_id');
    }

    // 下单用户
    public function user()
    {
        return $this->belongsTo('\Modules\User\Entities\User', 'user_id');
    }

    // 佣金记录
    public function brokerages()
    {
        return $this->hasMany('\Modules\Agent\Entities\Brokerage', 'order_id');
    }

    // 使用的优惠券
    public function coupons()
    {
        return $this->hasMany('\Modules\Coupon\Entities\UserCoupon', 'order_id');
    }

    // 所属活动
    public function activity()
    {
        $class = config('activity.map')[$this->activity_type];
        return $this->belongsTo($class, 'activity_id');
    }

    // 发货记录
    public function deliver_record()
    {
        return $this->hasOne('\Modules\Order\Entities\DeliverRecord', 'order_id')->where('deliver_type', 0);
    }

    // 支付记录
    public function payment_record()
    {
        return $this->hasOne('\Modules\Payment\Entities\PaymentRecord', 'order_id')->where('status', 2);
    }

    public function exchange_record()
    {
        return $this->belongsTo('\Modules\Market\Entities\ExchangeRecord', 'exchange_record_id');
    }

    // public function union_order()
    // {
    //     return $this->belongsTo('\Modules\Order\Entities\UnionOrder', 'union_order_id');
    // }

    // 此订单的分销记录
    public function agent_records()
    {
        return $this->hasMany('\Modules\Agent\Entities\AgentRecord', 'order_id');
    }

    public function payment()
    {
        return $this->payment_record ?: $this->union_order->payment_record;
    }

    public function getIsCloseableAttribute()
    {
        return $this->type !== 'package';
    }

    public function getActivityTypeTextAttribute()
    {
        $map = [
            'lottery' => '抽奖',
            'seckill' => '秒杀',
        ];

        return @$map[$this->activity_type];
    }

    public function getUnionStatusAttribute()
    {
        $status = 'unknow';

        if ($this->invoice_status === 1)
            $status = 'invoice_pending';
        elseif ($this->status === 3)
            $status = 'close_pending';
        elseif ($this->status === 4)
            $status = 'aftersale_pending';
        elseif ($this->status === 5)
            $status = 'aftersale_completed';
        elseif ($this->status === 9) {
            $status = $this->commented_at ? 'completed' : 'comment_pending';
        }
        elseif ($this->status === 6) {
            $status = 'covered';   // 已兑换成碎片
        }
        elseif ($this->status === 10) {
            $status = 'change';    // 转
            // $status = 'not_';      // 库存不足，全额退款
        }
        elseif ($this->status === 7) {
            if ($this->pay_status == 2)
                $status = 'pending';
            else
                $status = 'pay_pending';
        }
        elseif ($this->status === 8)
            $status = 'return_sale';
        elseif ($this->status === 0)
            $status = 'confirm_pending';
        elseif ($this->status === 2)
            $status = 'closed';
        elseif ($this->status === 1) {
            if ($this->pay_status === 0)
                $status = 'pay_pending';
            elseif ($this->pay_status === 1)
                $status = 'pay_confirm_pending';
            elseif ($this->pay_status === 2) {
                if ($this->deliver_status === 3) 
                    $status = 'delivered';
                elseif (!$this->deliver_status)
                    $status = 'deliver_pending';
            }
        }

        return $status;
    }

    // 关闭原因
    // public function getClosedByTextAttribute()
    // {
    //     $map = [
    //         0 => '用户取消',
    //         2 => '后台关闭',
    //         3 => '支付超时',
    //         4 => '风控关闭',
    //         5 => '拼团失败'
    //     ];

    //     return @v($map[$this->closed_by], '');
    // }

    public function getUnionStatusTextAttribute()
    {
        $map = [
            'aftersale_pending' => '售后中',
            'aftersale_completed' => '售后完成',
            'completed' => '已完成',
            'confirm_pending' => '待确认',
            'closed' => '已关闭',
            'pay_pending' => '待付款',
            'pay_confirm_pending' => '付款确认中',
            'deliver_pending' => '待发货',
            'delivered' => '待收货',
            // 'comment_pending' => '待评价',
            'comment_pending' => '已完成',
            'invoice_pending' => '发票申请中', 
            'close_pending' => '申请取消中',
            'pending' => '待用户处理',
            'return_sale' => '已返售',
            'covered' => '已兑换'
        ];

        return @v($map[$this->union_status], '未知状态');
    }

    // 展示在列表的订单及可被导出的订单类型
    public function scopeDisplayAtClient($query)
    {
        return $query->whereIn('type', ['product', 'asset', 'box', 'activity', 'package'])->where('is_visible', 1);
    }

    public function scopeType($query, $type)
    {
        if ($type === 'all') {
            // 全部订单
            return $query;
        }
        else if ($type === 'other') {
            // 管理后台的 其它订单
            return $query->whereIn('type', ['asset', 'vip', 'jika']);
        }
        // else if ($type  === 'redpack_deposit') {
        //     return $query->where('type')
        // }
        // else if ($type === 'score_deposit') {
        //     return $query->where('type', '')
        // }
        // \Log::error($type);
        
        return $query->where('type', $type);
    }

    // 包含某sku的订单
    public function scopeHasSku($query, $sku)
    {
        return $query->whereHas('skus', function ($q) use ($sku) {
            return $q->where('sku_id', $sku->id);
        });
    }

    // 包含某sku编号
    public function scopeHasSkuNumber($query, $skuNumber)
    {
        return $query->whereHas('skus', function ($q) use ($skuNumber) {
            return $q->where('number', $skuNumber);
        });
    }

    public function scopeNotType($query, $type)
    {
        return $query->where('type', '<>', $type);
        // return $query->where('type', 'box');
    }

    public function scopeSearch($query, $key)
    {
        if (!$key)
            return $query;

        return $query->where('number', 'like', '%' . $key . '%')->orWhereHasIn('user', function ($q) use ($key) {
            // return $q->whereHas('user', function ($qq) {
                return $q->where('phone', 'like', '%' . $key . '%')->orWhere('name', 'like', '%' . $key . '%');
            // });
        })->orWhereHasIn('address', function ($q) use ($key) {
            return $q->where('phone', 'like', '%' . $key . '%')->orWhere('consignee', 'like', '%' . $key . '%');
        })->orWhereHasIn('skus', function ($q) use ($key) {
            return $q->where('number', $key)->orWhere('title', 'like', '%' . $key . '%')->orWhere('pay_order_number', $key);
        });
    }

    public function scopePaid($query)
    {
        return $query->where('pay_status', 2);
    }

    public function scopeVisible($query)
    {
        return $query->where('is_visible', 1);
    }

    public function scopeUser($query, $user)
    {
        return $query->where('user_id', $user->id);
    }

    public function scopeMiniappType($query, $type)
    {
        if ($type === 'tmail') {
            return $query->where('miniapp_type', 'ali');
        }
        elseif ($type === 'wechat') {
            return $query->where('miniapp_type', 'wechat');
        }

        return $query;
    }

    public function scopeStatus($query, $status) 
    {
        // 售后中有两种
        if ($status === 'aftersale_pending') {
            // \Log::error($status);
            return $query->where('status', 4)->orWhere('status', 3)->orWhere('aftersale_status', 1);
        }

        $map = [
            'working' => [
                'status' => 1,
            ],
            'pending' => [
                'status' => 7,
                'pay_status' => 2
            ],
            'confirm' => [
                'status' => 8
            ],
            'backed' => [
                'status' => 8
            ],
            'pay_pending' => [
                'status' => 1,
                'pay_status' => 0
            ],
            'deliver_pending' => [
                'status' => 1,
                'pay_status' => 2,
                'deliver_status' => 0
            ],
            'delivered' => [
                'status' => 1,
                'pay_status' => 2,
                'deliver_status' => 3
            ],
            'comment_pending' => [
                'status' => 9,
                'commented_at' => NULL
            ],
            'commented' => [
                'status' => 9,
                ['commented_at', '<>', NULL]
            ],
            'closed' => [
                'status' => 2
            ],
            'close_pending' => [
                'status' => 3
            ],
            'completed' => [
                'status' => 9
            ],
            // 'aftersale_pending' => [
            //     'status' => 4
            // ],
            'marked' => [
                ['marked_at', '<>', NULL]
            ],
            'offline_used' => [
                'status' => 9,
                ['offline_use_at', '<>', NULL]
            ]
        ];

        return $query->where($map[$status]);
    }

    static public function initWith($skuableMaps, $user, $address = NULL, $options = [])
    {
        $class = get_called_class();

        // \Log::error($class);

        $skuTotal = 0;

        foreach ($skuableMaps as $key => $skuableMap) {
            if (is_array($skuableMap['skuable']))
                $skuableMaps[$key]['skuable'] = new Sku($skuableMap['skuable']);

            if ($skuableMap['total'] <= 0) {
                ThrowException::Conflict('下单数量不能为0~');
            }
            
            $skuTotal += $skuableMap['total'];
        }

        $orderSkusTemp = array_map(function ($skuableMap) {
            return OrderSku::initWith($skuableMap['skuable'], $skuableMap['total'], [
                    'activity' => @$skuableMap['activity'],
                    'group_price' => @$skuableMap['group_price']
                ]);
        }, $skuableMaps);

        $moneyPrice = 0;
        $scorePrice = 0;

        // 供应商
        $supplier = NULL;

        // 计算
        foreach ($orderSkusTemp as $orderSku) {
            $moneyPrice += $orderSku->calcMoneyPrice();
            $scorePrice += $orderSku->calcScorePrice();

            // 取最后一个供应商作为订单供应商
            if ($orderSku->supplier) {
                $supplier = $orderSku->supplier;
            }
        }

        // foreach ($skuableMaps as $skuableMap) {
        //     $productPrice += $skuableMap['skuable']->sellingPrice('money', ['activity' => $activity]) * $skuableMap['total'];
        //     $scorePrice += $skuableMap['skuable']->sellingPrice('score', ['activity' => $activity]) * $skuableMap['total'];
        // }

        $carriage = @$options['carriage'] ?: 0;
        $carriageType = @$options['carriage_type'] ?: 1;

        // 订单总价格
        $orderMoneyPrice = $moneyPrice + $carriage;
        $orderScorePrice = $scorePrice;

        // $couponDiscount = 0;
        // $vipDiscount = 0;
        // $scoreDiscount = 0;
        // $redPacketDiscount = 0;

        // 需要支付价格
        // $payPrice = $orderPrice + $carriage - $couponDiscount - $vipDiscount - $scoreDiscount - $redPacketDiscount;
        $payMoneyPrice = $orderMoneyPrice;
        $payScorePrice = $orderScorePrice;

        $order = new $class([
            'user_id' => $user->id,
            'product_total' => count($skuableMaps),
            'sku_total' => $skuTotal,
            'product_money_price' => $moneyPrice,
            'product_score_price' => $scorePrice,
            'order_money_price' => $orderMoneyPrice,
            'order_score_price' => $orderScorePrice,
            'pay_money_price' => $payMoneyPrice,
            'pay_score_price' => $payScorePrice,
            'pay_status' => 0, 
            // 'client_name' => @$options['client_name'],
            // 'client_type' => @$options['client_type'],
            // 'os_type' => @$options['os_type'],
            'type' => $class::$orderType,
            'vip_discount' => 0,
            'coupon_discount' => 0,
            'score_discount' => 0,
            'carriage' => $carriage,
            'carriage_type' => $carriageType,
            'miniapp_type' => 'wechat',
            'remark' => @$options['remark'],
            'sharer' => @$options['sharer'],
            'is_visible' => static::$isVisible ? 1 : 0
        ]);

        $order->skusTemp = $orderSkusTemp;
        // $order->skusTemp = array_map(function ($skuableMap) use ($activity) {
        //     return OrderSku::initWith($skuableMap['skuable'], $skuableMap['total'], ['activity' => $activity]);
        // }, $skuableMaps);

        $order->tempUser = $user;

        if ($address)
            $order->addressTemp = OrderAddress::initWith($address);

        $order->is_need_address = 0;
        foreach ($skuableMaps as $skuableMap) {
            if ($skuableMap['skuable']->isNeedAddress()) {
                $order->is_need_address = 1;
                break;
            }
        }

        // 标记活动类型
        if (@$options['node']) {
            $node = $options['node'];
            $order->node_type = $node->getType('node_type');
            $order->node_id = $node->id;
            $order->node_uuid = $node->uuid;
            // $order->activity_status = 2;
        }

        // 房间
        if (@$options['room']) {
            $order->room_id = $options['room']->id;
        }

        // 标记活动类型
        if (@$options['activity']) {
            $activity = $options['activity'];
            $order->activity_type = $activity->activity_type;
            $order->activity_id = $activity->id;
            // $order->activity_status = 2;
        }

        // 使用兑换
        if (@$options['cover_type']) {

            if  (count($skuableMaps) !== 1) {
                ThrowException::Conflict('sku not allow');
            }

            if ($skuableMaps[0]['total'] !== 1) {
                ThrowException::Conflict('单次仅可兑换一件');
            }

            if ($options['cover_type'] === 'chip') {
                // 计算碎片id
                $sku = $skuableMaps[0]['skuable'];
                $total = $skuableMaps[0]['total'];

                if (!$sku->cover_chip_status) {
                    ThrowException::Conflict('此商品不支持使用碎片兑换~');
                }

                // 检查是否有足够的碎片
                $chipId = $sku->cover_chip_id;
                $chipTotal = $sku->cover_chip_total * $total;

                $user->checkChipTotalEnough($chipId, $chipTotal) || ThrowException::Conflict('碎片资产不足，无法兑换');

                $order->useCoverDiscount([
                    'cover_type' => 'chip',
                    'cover_asset_id' => $chipId,
                    'cover_asset_total' => $chipTotal
                ]);
            }
        }

        // 使用置换
        if (@$options['exchange_record']) {
            $order->useExchangeDiscount($options['exchange_record']);
            $order->tempExchangeRecord = $options['exchange_record'];
        }

        // 计算多买优惠 (如福袋多开等)
        $order->calcMultiBuyDiscount();

        // 使用优惠券
        if (isset($options['coupon'])) {
            $order->useCoupon($options['coupon']);
        }

        // 使用红包
        // @$options['is_use_redpack'] 可能为unselect
        if (@$options['is_use_redpack']) {
            $order->useRedpack($user);
        }

        // 使用红包
        if (@$options['is_use_score']) {
            $order->useScore($user);
        }


        // 需要记录进options字段的内容
        if (@$options['options']) {
            $order->options = @$options['options'];
        }

        return $order;
    }

    // 扣库存
    public function addSales()
    {
        // 已扣过库存
        if ($this->is_add_sales) {
            return true;
        }

        DB::beginTransaction();

        foreach ($this->skus as $orderSku) {
            if (!$orderSku->addSales()) {
                return false;
            }
        }

        $this->update([
            'is_add_sales' => 1
        ]);

        DB::commit();

        return true;
    }

    public function createAll($options = [])
    {
        $this->number = $this->generateNumber();
        $this->pay_number = $this->number;
        
        $this->code = $this->generateCode();
        $this->uuid = uniqid();

        $this->auto_closed_at = $this->calcAutoClosedAt();

        // 使用置换
        if ($this->tempExchangeRecord) {
            $this->tempExchangeRecord->createAll($this);
            $this->exchange_record_id = $this->tempExchangeRecord->id;
        }


        $this->save();

        $this->skus()->saveMany($this->skusTemp);

        // 保存收货地址
        if ($this->addressTemp)
            $this->address()->save($this->addressTemp);

        // 扣除库存
        // 默认创建订单时就要扣除库存，除非指定不创建时不扣除
        $isNeedAddSales = @$options['is_add_sales_disabled'] ? false : true; 
        if ($isNeedAddSales) {
            $this->addSales() || ThrowException::Conflict('库存不足哦~');
        }

        // 使用红包
        if ($this->redpack_discount && $this->tempUser->id>300) {
            $this->tempUser->asset('redpack')->out($this->redpack_discount, [
                'description' => '订单抵扣',
                'order' => $this
            ]) || ThrowException::BalanceNotEnought();
        }

        // 使用积分抵扣
        if ($this->score_used && $this->tempUser->id>300) {
            $this->tempUser->asset('score')->out($this->score_used, [
                'description' => '订单抵扣',
                'order' => $this
            ]) || ThrowException::ScoreNotEnought();
        }

        // 使用优惠券
        if ($this->userCouponTemp)
            $this->userCouponTemp->use($this);

        // 支付积分部分
        if ($this->pay_score_price) {
            $this->payScorePrice() || ThrowException::ScoreNotEnought();
        }

        // 使用兑换
        if ($this->cover_type) {
            // 使用碎片兑换
            if ($this->cover_type === 'chip') {
                $this->user->chipAsset($this->cover_asset_id)->out($this->cover_asset_total, [
                        'description' => '订单兑换',
                        'order' => $this
                    ]);
            }
        }

        // 绑定设备
        $this->markDevice();

        $this->confirm();

        // 进行同步操作
        $this->createdListenerSync();

        // 如果不需要支付人民币，则直接置为已支付状态
        if (!$this->pay_money_price) {
            //同时判断此商品是否是盲盒商品，供应链商品，如果是酒推送订单
            
            $this->completePay([
                'pay_type' => 'none'    // 无须支付
            ]);
        }

        return $this;
    }

    // 创建后回调
    public function createdListenerSync()
    {
        // 由子类实现
    }

    public function payScorePrice()
    {
        if ($this->pay_score_price) {
            $payStatus = $this->user->asset('score')->out($this->pay_score_price, [
                'description' => '订单支付',
                'order' => $this
            ]);

            $this->update([
                'score_paid_at' => now()
            ]);

            return $payStatus;
        }
        return true;
    }

    public function updateAddress($address) 
    {
        if ($this->address)
            $this->address->delete();

        $this->address()->save(OrderAddress::initWith($address));
    }

    public function calcAutoClosedAt()
    {
        $autoClosedTimeout = static::$autoClosedTimeout ?: Setting::get('order.auto_closed_timeout');
        return date('Y-m-d H:i:s', strtotime('+' . $autoClosedTimeout . ' minutes'));
    }

    // 计算多买优惠 (目前仅适用于同一sku购买多件时的情况)
    public function calcMultiBuyDiscount()
    {
        $scoreSumDiscount = 0;
        $moneySumDiscount = 0;

        foreach ($this->skusTemp as $orderSku) {
            list($money, $score) = $orderSku->skuable->calcMultiBuyDiscount($orderSku->total);

            $moneySumDiscount += $money;
            $scoreSumDiscount += $score;
        }

        $this->multi_buy_money_discount = $moneySumDiscount;
        $this->multi_buy_score_discount = $scoreSumDiscount;

        $calc = $this->pay_money_price - $moneySumDiscount;
        $this->pay_money_price = $calc < 0 ? 0 : $calc;

        $calc = $this->pay_score_price - $scoreSumDiscount;
        $this->pay_score_price = $calc < 0 ? 0 : $calc;
    }

    // 计算兑换
    public function useExchangeDiscount($exchangeRecord)
    {
        $this->exchange_record_id = @$exchangeRecord->id;
        
        $scoreSumDiscount = $exchangeRecord->source_score_price;
        $moneySumDiscount = $exchangeRecord->source_money_price;

        $this->exchange_money_discount = $moneySumDiscount;
        $this->exchange_score_discount = $scoreSumDiscount;

        $calc = $this->pay_money_price - $moneySumDiscount;
        $this->pay_money_price = $calc < 0 ? 0 : $calc;

        $calc = $this->pay_score_price - $scoreSumDiscount;
        $this->pay_score_price = $calc < 0 ? 0 : $calc;
    }

    // 使用红包
    public function useRedpack($user)
    {
        $this->isUseRedpack = 1;
        $this->redpack_discount = $this->calcUsableRedpack($user);
        $calc = $this->pay_money_price - $this->redpack_discount;
        $this->pay_money_price = $calc < 0 ? 0 : $calc;
    }

    // 使用免费次数
    public function useFreeTicket()
    {
        $this->pay_score_price = 0;
        $this->pay_money_price = 0;
        $this->is_use_free_ticket = 1;
    }

    // 使用积分
    public function useScore($user)
    {
        $score = $this->calcUsableScore($user);
        $scoreDiscount = Setting::coverScoreToMoney($score);

        $this->score_discount = $scoreDiscount;
        $calc = $this->pay_money_price - $scoreDiscount;
        $this->pay_money_price = $calc < 0 ? 0 : $calc;

        $this->score_used = $score;
    }

    // 使用兑换
    public function useCoverDiscount($options)
    {
        $this->cover_discount = $this->product_money_price;
        // $calc = $this->pay_money_price - $this->cover_discount;
        $this->pay_money_price = 0;
        $this->pay_score_price = 0;
        // $this->pay_money_price = $calc < 0 ? 1 : $calc;

        $this->cover_type = @$options['cover_type'];
        $this->cover_asset_id = @$options['cover_asset_id'];
        $this->cover_asset_total = @$options['cover_asset_total'];
    }

    public function useCoupon($userCoupon)
    {
        $this->coupon_discount = $userCoupon->base_coupon->calcDiscountMoney($this);
        $calc = $this->pay_money_price - $this->coupon_discount;
        $this->pay_money_price = $calc < 0 ? 1 : $calc;

        $this->coupon_id = $userCoupon->id;

        $this->userCouponTemp = $userCoupon;
    }


    static public function beforeGetList($options)
    {
        if (isset($options['status']) && $options['status'] !== 'all')
            $options['scopes']['status'] = $options['status'];

        if (@$options['type']) 
            $options['scopes']['type'] = $options['type'];

        if (@$options['miniapp_type']) {
            $options['scopes']['miniappType'] = $options['miniapp_type'];
        }

        $options['where']['is_visible'] = 1;

        if (@$options['created_at_start']) {
            array_push($options['where'], [
                'created_at', '>=', $options['created_at_start']
            ]);
        }

        if (@$options['created_at_end']) {
            array_push($options['where'], [
                'created_at', '<=', $options['created_at_end']
            ]);
        }

        if (@$options['paid_at_start']) {
            array_push($options['where'], [
                'money_paid_at', '>=', $options['paid_at_start']
            ]);
        }

        if (@$options['paid_at_end']) {
            array_push($options['where'], [
                'money_paid_at', '<=', $options['paid_at_end']
            ]);
        }

        if (@$options['money_price_min']) {
            array_push($options['where'], [
                'product_money_price', '>=', intVal($options['money_price_min'])
            ]);
        }

        if (@$options['money_price_max']) {
            array_push($options['where'], [
                'product_money_price', '<=', intVal($options['money_price_max'])
            ]);
        }

        if (@$options['sku_number']) {
            $options['scopes']['hasSkuNumber'] = $options['sku_number'];
        }

        return $options;
    }

    // 获取具体实现的派生订单类实例
    static public function getDerivedOrder($where)
    {
        $record = DB::table('orders')->where($where)->first();

        if (!$record) 
            return null;

        $orderType = $record->type ?: 'normal';
        $class = @config('order.map')[$orderType] ?: get_called_class();

        $order = $class::getEntity([
            'id' => $record->id
        ], false);

        return $order;
    }

    // 获取此订单的派生类
    public function derivedOrder()
    {
        $orderType = $this->type ?: 'normal';
        $class = @config('order.map')[$orderType] ?: get_called_class();

        $order = $class::getEntity([
            'id' => $this->id
        ], false);

        return $order;
    }

    public function generateNumber()
    {
        $number = 'P' . date('mdHis') . $this->user_id . '0' . $this->tenant_id . rand(100, 999);
        return $number;
    }

    public function generateCode()
    {
        $code = rand(1000, 9999) . strVal(time()) . $this->user_id . '0' . $this->tenant_id . rand(100000, 999999);

        return substr($code, -16);
    }

    // 计算一个订单最高可用红包抵扣的数量
    public function calcUsableRedpack($user)
    {
        $orderRate = floatVal(@Setting::get('sys_redpack')['order_rate'] ?: 0);
        $orderRate = $orderRate > 100 ? 100 : $orderRate;

        $payPrice = $this->order_money_price - $this->multi_buy_money_discount;
        if ( $this->coupon_discount > 0 ){
            // 红包支付扣除优惠券抵扣
            $payPrice = $payPrice - $this->coupon_discount;
            $payPrice = max($payPrice, 0);
        }
        $calc = intVal($payPrice * $orderRate / 100);

        if($user->id>300){
            $balance = $user->asset('redpack')->balance;
        }else{
            $balance = 99999999;
        }
        

        return $calc > $balance ? $balance : $calc;
    }

    // 计算一个订单最高可用积分抵扣的数量
    public function calcUsableScore($user) 
    {
        $setting = @Setting::get('sys_score');

        // 不允许订单抵扣
        if (!@$setting['is_pay_enabled']) {
            return 0;
        }

        // 当前订单类型不在可用订单类型中
        $payableOrderTypeMap = @$setting['payable_order_type'] ?: [];
        // \Log::error($this->node_type);
        // \Log::error($payableOrderTypeMap);
        if (!in_array($this->node_type ?: 'product', $payableOrderTypeMap)) {
            return 0;
        }

        if ($this->score_used) {
            return $this->score_used;
        }

        // 最高抵扣比例
        $maxPercent = (@$setting['max_pay_percent'] ?: 0) / 100;
        $maxMoney = floor($this->pay_money_price * $maxPercent);

        // 最高可使用积分
        $maxScore = Setting::coverMoneyToScore($maxMoney);

        $balance = $user->asset('score')->balance;

        return $maxScore > $balance ? $balance : $maxScore;
    }

    public function title()
    {
        $str = $this->skus[0]->title;

        if ($this->skus->count() > 1)
            $str .= '(等多件)';

        return mb_substr(trim($str), 0, 63);
    }

    public function payPrice()
    {
        return $this->pay_money_price;
    }

    public function payNumber()
    {
        return $this->pay_number;
    }

    // 佣金是否可以发放了
    public function isBrokerageCompletable()
    {
        return $this->status === 9;
    }

    // 微信平台上的支付
    public function payByWechat($subType = 'miniapp', $user = NULL)
    {
        $user = $user ?: $this->user;
        $clientName = Auth::clientName();

        return Payment::wechatPay($clientName, $subType)->config($user, $this);
    }

    // 支付宝支付
    public function payByAlipay($subType = 'app', $user = NULL)
    {
        $user = $user ?: $this->user;
        $clientName = Auth::clientName();

        return Payment::aliPay($clientName, $subType)->config($user, $this);
    }

    // 抖音系平台上的支付
    public function payByByteDance($subType = 'wechat', $user = NULL)
    {
        $user = $user ?: $this->user;
        $clientName = Auth::clientName();

        return Payment::byteDancePay($clientName, $subType)->config($user, $this);
    }

    // 快手平台上的支付
    public function payByKuaishou($subType = 'wechat', $user = NULL)
    {
        $user = $user ?: $this->user;
        $clientName = Auth::clientName();

        return Payment::kuaishouPay($clientName, $subType)->config($user, $this);
    }

    // 结算快手平台上的单号
    public function completeForKuaishou()
    {
        $subType = 'wechat';
        $clientName = '';
        $flag = Payment::kuaishouPay($clientName, $subType)->completeOrder($this);

        if ($flag) {
            $this->update([
                'is_kuaishou_order_completed' => 1
            ]);
        }

        return $flag;
    }

    // 快手平台上的支付
    public function payByZhongjin($subType = 'wechat', $user = NULL)
    {
        $user = $user ?: $this->user;
        $clientName = Auth::clientName();

        return Payment::zhongjinPay($clientName, $subType)->config($user, $this);
    }

    // 按百份比退
    public function refundByPercent($percent = 1, $options = []) {
        if ($this->pay_money_price) {
            $value = ceil($this->pay_money_price * $percent);
            $this->refund('money', $value, $options);
        }

        if ($this->pay_score_price) {
            $value = ceil($this->pay_score_price * $percent);
            $this->refund('score', $value, $options);
        }
    }

    // $value 为要退款的金额, NULL为全额退
    // $type 为money时退人民币  为score时退积分 为all时全款退
    public function refund($type = 'all', $value = NULL, $options = [])
    {
        // 退人民币
        if ($type === 'money' || $type === 'all') {
            $value = is_null($value) ? $this->pay_money_price : $value;
            if ($value) {
                $clientName = $this->client_name;
                Payment::wechatPay($clientName, 'miniapp')->refundMoney($this, $value, $options);
            }
        }

        // 退积分
        if ($type === 'score' || $type === 'all') {
            $value = $value ?: $this->pay_score_price;
            if ($value)
                $this->user->asset('score')->in($value, [
                    'description' => '订单退款',
                    'order' => $this
                ]);
        }

        // \Log::error($type);

        // 退红包
        if ($type === 'redpack' || $type === 'balance') {
            if ($value)
                $this->user->asset('redpack')->in($value, [
                    'description' => '订单退款',
                    'order' => $this
                ]);
        }
    }

    // 确认订单
    public function confirm()
    {
        if ($this->status != 0)
            return false;

        $this->status = 1;
        $this->confirmed_at = now();
        $this->save();
    }

    // 完成支付
    public function completePay($options, $isUnionOrderPay = false)
    {
        // 此订单不是待支付状态
        if ($this->union_status !== 'pay_pending') {
            return false;
        }


        $this->pay_status = 2;
        $this->money_paid_at = date('Y-m-d H:i:s');
        $this->pay_type = @$options['pay_type'];
        $this->pay_sub_type = @$options['pay_sub_type'];
        
        $this->save();

        // 优惠券已使用统计+1
        if ($this->coupon_id) {
            $coupon = UserCoupon::where('id', $this->coupon_id)->first();
            if ($coupon) {
                $coupon->use($this);
            }
        }

        // 置换记录标记为已完成
        if ($this->exchange_record_id && $this->exchange_record) {
            $this->exchange_record->complete();
        }

        // 进行积分奖励操作
        foreach ($this->skus as $orderSku) {
            // 积分奖励
            $orderSku->sendProductReward();
        }

        // 广播订单完成事件
        event(new \Modules\Order\Events\OrderPaidEvent($this));

        // 进行同步操作
        $flag = $this->paidListenerSync();

        // 自动标记订单已完成 
        if ($this->isAutoComplete && $flag) {
            $this->auto_completed_at = now();
            $this->complete();
            // $this->update([
            //     'auto_completed_at' => now()
            // ]);
        }
    }

    // 发货
    public function deliver($options)
    {
        $this->deliver_record()->create([
            'uuid' => uniqid(),
            'deliver_type' => 0,
            'type' => @$options['type'],
            'content' => @$options['content'],   // 线上发货内容
            'remark' => @$options['remark'],
            'express_name' => @$options['express_name'],
            'express_number' => @$options['express_number']
        ]);

        $this->deliver_status = 3;
        $this->delivered_at = date('Y-m-d H:i:s');
        $this->save();

        // $this->user->notify(new \Modules\Order\Notifications\OrderDelivered($this));
    }

    // 更新发货信息
    public function updateDeliverInfo($options)
    {
        $deliver = $this->deliver_record()->first();

        $deliver->update([
            'deliver_type' => 0,
            'type' => @$options['type'],
            'content' => @$options['content'],   // 线上发货内容
            'remark' => @$options['remark'],
            'express_name' => @$options['express_name'],
            'express_number' => @$options['express_number']
        ]);
        // $this->user->notify(new \Modules\Order\Notifications\OrderDelivered($this));
    }

    // 用户关闭订单
    public function closeByUser($reason)
    {
        $this->close(2, $reason ?: '用户关闭');
    }

    public function closeByPayTimeout()
    {
        $this->close(3, '支付超时');
    }

    public function closeByGrouponTimeout()
    {
        $this->close(5, '拼团失败');
    }

    public function coverToChip()
    {
        $this->update([
            'status' => 6
        ]);
    }

    // 关闭订单
    public function close($closedBy, $reason = null)
    {
        if ($this->union_status !== 'pay_pending' && $this->union_status !== 'deliver_pending')
            ThrowException::Conflict('当前订单暂不可取消');
        // if ($this->status === 2)
        //     ThrowException::Conflict('当前订单暂不可取消');

        // 已支付订单在支付30s内不可取消
        if ($this->pay_status === 2) {
            $randSecond = rand(30, 40);   // 随机30-40s
            $str = date('Y-m-d H:i:s', strtotime('-' . $randSecond . ' seconds'));
            if ($this->money_paid_at && $this->money_paid_at > $str) {
                ThrowException::Conflict('订单支付30秒内不可退款~');
            }

            if ($this->score_paid_at && $this->score_paid_at > $str) {
                ThrowException::Conflict('订单支付30秒内不可退款~');
            }
        }

        $this->closed_by = $closedBy;
        $this->closed_reason = $reason;
        $this->closed_at = now();

        // 已支付则为申请取消中，未支付则直接取消成功
        $this->status = $this->union_status === 'pay_pending' ? 2 : 3;

        $this->save();

        // 退款后退回优惠券
        if ($this->status == 2) {
            $this->closedSync();

            // 广播订单关闭事件
            event(new \Modules\Order\Events\OrderClosedEvent($this));
        }
    }

    // 取消退款申请
    public function cancelRefund()
    {
        if ($this->status !== 3) {
            ThrowException::Conflict('订单不在申请退款中，无法取消');
        }

        $this->update([
            'status' => 1
        ]);
    }

    // 退款并关闭订单
    // closeBy  2为管理后台关闭 其它参考数据库中orders表的closed_by字段注释
    public function closeAndRefund($closedBy, $reason = null, $options = [])
    {
        $moneyRefund = @$options['refund_money'];
        $balanceRefund = @$options['refund_balance'];
        $scoreRefund = @$options['refund_score'];

        if ($this->status === 2) {
            ThrowException::Conflict('订单已是关闭状态，无法重复关闭');
        }

        $this->closed_by = $closedBy;
        $this->closed_reason = $reason;
        $this->closed_at = now();
        $this->status = 2;

        // 只退人民币， 积分会在订单关闭时自动触发退款
        if ($moneyRefund) {
            $this->refund('money', $moneyRefund);
        }

        if ($balanceRefund) {
            $this->refund('balance', $balanceRefund);
        }

        $this->save();

        $this->closedSync();
    }

    public function closedSync()
    {
        // 退款后需要进行退回优惠券
        foreach ($this->coupons as $userCoupon) {
            $userCoupon->release();
        }

        // 已扣库存的需要增加回库存 
        if ($this->is_add_sales && !($this->type === 'activity' && $this->node_type === 'yifanshang')) {
            foreach ($this->skus as $orderSku) {
                $orderSku->reduceSales();
            }
        }

        // 退红包
        if ($this->redpack_discount) {
            $this->user->asset('redpack')->in($this->redpack_discount, [
                'description' => '订单关闭',
                'order' => $this
            ]);
        }

        // 退兑换的内容（碎片、积分等）
        if ($this->cover_type) {
            // 使用碎片兑换
            if ($this->cover_type === 'chip') {
                $this->user->chipAsset($this->cover_asset_id)->in($this->cover_asset_total, [
                        'description' => '订单取消',
                        'number' => $this
                    ]);
            }
        }

        // 退置换的物品 (如果是置换订单有此步)
        if ($this->exchange_record_id && $this->exchange_record) {
            $this->exchange_record->close();
        }

        // 退积分（支付部分）
        if ($this->pay_score_price) {
            $this->user->asset('score')->in($this->pay_score_price, [
                'description' => '订单关闭',
                'order' => $this
            ]);
        }

        // 退积分 (抵扣部分)
        if ($this->score_used) {
            $this->user->asset('score')->in($this->score_used, [
                'description' => '订单关闭',
                'order' => $this
            ]);
        }

        // 关闭
        $this->closedListenerSync();
    }

    // 关闭事件
    public function closedListenerSync()
    {
        // 此处由派生类中实现
    }
    public function jiqirenGenerateResponse($options = [])
    {
        // $clientType 暂时不使用

        $isNeedPay =  $this->pay_money_price ? 1 : 0;

        $res = [
            'order' => [
                'id' => $this->id,
                'uuid' => $this->uuid,
            ],
            'is_need_pay' => 0
        ];

        if ($isNeedPay) {

            list($platformType, $platformSubType, $clientType, $osType) = array_values(Auth::deviceInfo());

            // for test
            // $platformType = 'app';

            // 使用第三方支付
            if (env('USE_OTHER_PAY') === 'zhongjin') {
                if ($platformType === 'wechat') {
                    // 微信小程序支付
                    $res['pay_config']  = $this->payByZhongjin('wechat');
                }
            }
            elseif ($platformType === 'wechat') {
                // 微信小程序支付
                if ($clientType === 'miniapp') {
                    $res['pay_config']  = $this->payByWechat('miniapp');
                }
            }
            elseif ($platformType  === 'byte_dance')  {
                // 抖音小程序支付 (暂时只支持微信支付)
                if ($clientType === 'miniapp') {
                    $res['pay_config'] = $this->payByByteDance('wechat');
                }
            }
            elseif ($platformType  === 'kuaishou')  {
                // 抖音小程序支付 (暂时只支持微信支付)
                if ($clientType === 'miniapp') {
                    $res['pay_config'] = $this->payByKuaishou('wechat');
                }
            }
            elseif ($platformType === 'app') {

                $payType = @$options['pay_type'] ?: 'select_pending';

                if ($payType === 'select_pending') {
                    // 如果同时配置app支付宝支付 和 微信支付
                    // 则需要返回 select_pending 在用户前端让用户选择哪种支付方式
                    $res['pay_type'] = 'select_pending';
                }
                elseif ($payType === 'alipay') {
                    // 仅配置有支付宝支付
                    $res['pay_type'] = 'alipay';
                    $res['pay_config'] = $this->payByAlipay('app');
                }
                elseif ($payType === 'wechat') {
                    // 仅配置有微信支付，app中使用微信支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('app');
                }

                // 仅配置有支付宝支付
                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
            elseif ($platformType === 'alipay') {
                // 支付宝小程序
                $res['pay_type'] = 'alipay';
                $res['pay_config'] = $this->payByAlipay('miniapp');

                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
            elseif ($platformType === 'web') {
                // H5网页
                
                // 如果是微信浏览器
                if (Auth::isWechatBroswer()) {
                    // 微信公众号支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('wechat_h5');
                }
                else {
                    ThrowException::Conflict('请在微信中打开页面购买~');
                    
                    // 普通h5支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('h5');
                }

                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
        }
        else {

        }

        return $res;
    }
    // 创建订单成功后返回的信息（统一）
    public function generateResponse($options = [])
    {
        // $clientType 暂时不使用

        $isNeedPay =  $this->pay_money_price ? 1 : 0;

        $res = [
            'order' => [
                'id' => $this->id,
                'uuid' => $this->uuid,
            ],
            'is_need_pay' => $isNeedPay
        ];

        if ($isNeedPay) {

            list($platformType, $platformSubType, $clientType, $osType) = array_values(Auth::deviceInfo());

            // for test
            // $platformType = 'app';

            // 使用第三方支付
            if (env('USE_OTHER_PAY') === 'zhongjin') {
                if ($platformType === 'wechat') {
                    // 微信小程序支付
                    $res['pay_config']  = $this->payByZhongjin('wechat');
                }
            }
            elseif ($platformType === 'wechat') {
                // 微信小程序支付
                if ($clientType === 'miniapp') {
                    $res['pay_config']  = $this->payByWechat('miniapp');
                }
            }
            elseif ($platformType  === 'byte_dance')  {
                // 抖音小程序支付 (暂时只支持微信支付)
                if ($clientType === 'miniapp') {
                    $res['pay_config'] = $this->payByByteDance('wechat');
                }
            }
            elseif ($platformType  === 'kuaishou')  {
                // 抖音小程序支付 (暂时只支持微信支付)
                if ($clientType === 'miniapp') {
                    $res['pay_config'] = $this->payByKuaishou('wechat');
                }
            }
            elseif ($platformType === 'app') {

                $payType = @$options['pay_type'] ?: 'select_pending';
                $payType = @$options['pay_type'] ?: 'alipay';

                if ($payType === 'select_pending') {
                    // 如果同时配置app支付宝支付 和 微信支付
                    // 则需要返回 select_pending 在用户前端让用户选择哪种支付方式
                    $res['pay_type'] = 'select_pending';
                }
                elseif ($payType === 'alipay') {
                    // 仅配置有支付宝支付
                    $res['pay_type'] = 'alipay';
                    $res['pay_config'] = $this->payByAlipay('app');
                }
                elseif ($payType === 'wechat') {
                    // 仅配置有微信支付，app中使用微信支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('app');
                }

                // 仅配置有支付宝支付
                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
            elseif ($platformType === 'alipay') {
                // 支付宝小程序
                $res['pay_type'] = 'alipay';
                $res['pay_config'] = $this->payByAlipay('miniapp');

                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
            elseif ($platformType === 'web') {
                // H5网页
                
                // 如果是微信浏览器
                if (Auth::isWechatBroswer()) {
                    // 微信公众号支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('wechat_h5');
                }
                else {
                    ThrowException::Conflict('请在微信中打开页面购买~');
                    
                    // 普通h5支付
                    $res['pay_type'] = 'wechat';
                    $res['pay_config'] = $this->payByWechat('h5');
                }

                // $res['pay_type'] = 'alipay';
                // $res['pay_config'] = $this->payByAlipay('app');
            }
        }
        else {

        }

        return $res;
    }
    public function jiqirenGeneratePreviewResponse($user, $options = [])
    {
        // $clientType 暂时不使用
        // 计算可用优惠券
        // $coupons = $this->filterCoupons($user->coupons()->with('base_coupon')->valid()->get());

        $orderInfo = [
            'max_useable_score' => $this->calcUsableScore($user),
            'redpack' => $this->product_money_price,
            'is_use_redpack' => 1,
            'is_use_score' => 0,
            'coupons' => ['usable'=>[],'unusable'=>[]],
            'carriage' =>0,
            'coupon_discount' => 0,
            'score_discount' => 0,
            'multi_buy_money_discount' => 0,
            'multi_buy_score_discount' => 0,
            'product_money_price' => $this->product_money_price,
            'product_score_price' => $this->product_score_price,
            'pay_money_price' => 0,
            'pay_score_price' => 0,
        ];

        $options['order'] = $orderInfo;

        return $options;
    }
    // 创建订单预览信息（统一）
    public function generatePreviewResponse($user, $options = [])
    {
        // $clientType 暂时不使用
        // 计算可用优惠券
        $coupons = $this->filterCoupons($user->coupons()->with('base_coupon')->valid()->get());

        $orderInfo = [
            'max_useable_score' => $this->calcUsableScore($user),
            'redpack' => $this->calcUsableRedpack($user),
            'is_use_redpack' => $this->isUseRedpack,
            'is_use_score' => $this->is_use_score,
            'coupons' => $coupons,
            'carriage' => $this->carriage,
            'coupon_discount' => $this->coupon_discount,
            'score_discount' => $this->score_discount,
            'multi_buy_money_discount' => $this->multi_buy_money_discount,
            'multi_buy_score_discount' => $this->multi_buy_score_discount,
            'product_money_price' => $this->product_money_price,
            'product_score_price' => $this->product_score_price,
            'pay_money_price' => $this->pay_money_price,
            'pay_score_price' => $this->pay_score_price,
        ];

        $options['order'] = $orderInfo;

        return $options;
    }

    public function complete()
    {
        $this->status = 9;
        $this->completed_at = now();
        $this->save();

        // 广播订单完成事件
        event(new \Modules\Order\Events\OrderCompletedEvent($this));

        // 进行同步操作
        $this->completedListenerSync();
    }

    // 线下核销码
    public function isOfflineUseable()
    {
        foreach ($this->skus as $sku) {
            if (@$sku->base_sku->parent_product->is_offline_useable)
                return true;
        }

        return false;
    }

    // 线下核销
    public function offlineUse()
    {
        // 订单完成
        $this->complete();

        $this->update([
            'offline_use_at' => now()
        ]);
    }

    // 支付完成后同步操作
    public function paidListenerSync()
    {
    }

    // 订单成功进行同步操作
    public function completedListenerSync()
    {
    }

    // 支付完成后异步操作
    public function paidListenerAsync()
    {
        // 商品
        // if (in_array($this->type, [
        //     'box',
        //     'product',
        //     'activity'
        // ])) {
        //     $this->user->notify(new \Modules\Order\Notifications\OrderPaid($this));
        // }
        // do something by other order type
    }

    public function isCouponUsable($userCoupon)
    {
        return $userCoupon->isUsable($this);
    }

    public function filterCoupons($userCoupons)
    {
        $usable = [];
        $unusable = [];

        foreach ($userCoupons as $userCoupon) {
            $info = $userCoupon->getInfo([
                'id',
                'uuid',
                'usable_start_at',
                'usable_end_at',
                'base_coupon' => [
                    'title',
                    'description',
                    'usable_range_type',
                    'money_limit_type',
                    'minimum_money',
                    'discount_type',
                    'discount_money',
                    'discount_rate',
                    'discount_money_limit',
                    'usable_range_text'
                ]
            ]);
            if ($this->isCouponUsable($userCoupon)) {
                array_push($usable, $info);
            }
            else
                array_push($unusable, $info);
        }

        return [
            'usable' => $usable, 
            'unusable' => $unusable
        ];
    }

    // 删除所有内容
    public function deleteAll()
    {
        $this->skus()->forceDelete();
        $this->forceDelete();
    } 

    // 将所有虚拟资产的sku发送给用户
    public function sendOnlineAssetToUser()
    {
        $user = $this->user;
        foreach ($this->skus as $orderSku) {
            if ($orderSku->base_sku->isOnlineSku()) {
                // 同一奖品同多次，使用多次发放，而非计算总和后一次发放
                for ($i=0; $i < $orderSku->total; $i++) { 
                    @$orderSku->base_sku->sendOnlineAssetToUser($user);
                }
            }
        }
    }

    // // 计算整个订单返售应该获得的金额
    // public function calcReturnSaleInfo()
    // {
    //     $money = 0;
    //     $redpack = 0;
    //     $score = 0;

    //     foreach ($this->offline_skus as $sku) {
    //         list($returnMoney, $returnRedpack, $returnScore) = $sku->calcReturnSaleInfo();

    //         $money += $returnMoney * $sku->total;
    //         $redpack += $returnRedpack * $sku->total;
    //         $score += $returnScore * $sku->total;
    //     }

    //     return [
    //         $money,
    //         $redpack,
    //         $score
    //     ];
    // }

    // 计算此订单可退款的金额
    public function calcRefundableMoney()
    {
        return $this->pay_money_price - $this->refunded_money;
    }

    // 是否可申请售后
    public function isAftersaleable()
    {
        return true;
    }
}
